Attribute Module_Name = "内嵌WPS文字AI插件V3"
/**
* 调用兼容OpenAI的大模型的JSA
* @功能：使用右键呼出菜单，并对WPS文字中的选中内容执行任务
* @作者：YsDirector
* @部分参考代码来源：TKing
* @version 3
* @date 2025-05-11
*/

const LOCALAI_API_URL = "API接口地址"; // API接口地址
const LOCALAI_MODEL = "加载的模型名称"; // 加载的模型名称
const LOCALAI_API_KEY = "输入令牌";//输入令牌


// 添加自定义右键菜单
function AIAutoRun() {
    var doc = Application.ActiveDocument;
    if (!doc) return;

    // 获取或创建上下文菜单栏
    var contextMenus = Application.CommandBars("Text");
    if (!contextMenus) return;

    // 检查是否已经存在名为 "AI" 的菜单项
    var aiMenu = null;
    for (var i = 1; i <= contextMenus.Controls.Count; i++) {
        if (contextMenus.Controls.Item(i).Caption === "AI（本功能由YsDirector编写）") {
            aiMenu = contextMenus.Controls.Item(i);
            break;
        }
    }

    // 如果不存在则创建新的菜单项
    if (!aiMenu) {
        aiMenu = contextMenus.Controls.Add(msoControlPopup);
        aiMenu.Caption = "AI（本功能由YsDirector编写）";
    } else {
        // 清空现有子菜单项
        while (aiMenu.Controls.Count > 0) {
            aiMenu.Controls.Item(1).Delete();
        }
    }

    // 添加子菜单项
    function addMenuItem(menu, caption, macroName) {
        var menuItem = menu.Controls.Add(msoControlButton);
        menuItem.Caption = caption;
        menuItem.OnAction = macroName;
    }

    addMenuItem(aiMenu, "聊天机器人（实验性功能）", "LocalAIChatingBot");
    addMenuItem(aiMenu, "————设置————", );
    addMenuItem(aiMenu, "插入模式", "LocalAISettings1");
    addMenuItem(aiMenu, "替换模式", "LocalAISettings2");
    addMenuItem(aiMenu, "修订模式", "LocalAISettings3");
    
    //初始化设置
    let LocalAISetting = 1;
    // 刷新屏幕
    Application.ScreenRefresh();
}

function LocalAISettings1(){
	LocalAISetting = 1;
	    var doc = Application.ActiveDocument;
    if (!doc) return;

    // 获取或创建上下文菜单栏
    var contextMenus = Application.CommandBars("Text");
    if (!contextMenus) return;

    // 检查是否已经存在名为 "AI" 的菜单项
    var aiMenu = null;
    for (var i = 1; i <= contextMenus.Controls.Count; i++) {
        if (contextMenus.Controls.Item(i).Caption === "AI（本功能由YsDirector编写）") {
            aiMenu = contextMenus.Controls.Item(i);
            break;
        }
    }

    // 如果不存在则创建新的菜单项
    if (!aiMenu) {
        aiMenu = contextMenus.Controls.Add(msoControlPopup);
        aiMenu.Caption = "AI（本功能由YsDirector编写）";
    } else {
        // 清空现有子菜单项
        while (aiMenu.Controls.Count > 0) {
            aiMenu.Controls.Item(1).Delete();
        }
    }

    // 添加子菜单项
    function addMenuItem(menu, caption, macroName) {
        var menuItem = menu.Controls.Add(msoControlButton);
        menuItem.Caption = caption;
        menuItem.OnAction = macroName;
    }

    addMenuItem(aiMenu, "扩写", "LocalAIProcess");
    addMenuItem(aiMenu, "翻译", "LocalAITranslate");
    addMenuItem(aiMenu, "语法检查和更正", "LocalAIGrammarly");
    addMenuItem(aiMenu, "摘要", "LocalAISummary");
    addMenuItem(aiMenu, "关键词", "LocalAIKeywords");
    addMenuItem(aiMenu, "自定义", "LocalAICustomize");
    addMenuItem(aiMenu, "聊天机器人（实验性功能）", "LocalAIChatingBot");
    addMenuItem(aiMenu, "————设置————", );
    addMenuItem(aiMenu, "插入模式（当前）", "LocalAISettings1");
    addMenuItem(aiMenu, "替换模式", "LocalAISettings2");
    addMenuItem(aiMenu, "修订模式", "LocalAISettings3");
        // 刷新屏幕
    Application.ScreenRefresh();
}

function LocalAISettings2(){
	LocalAISetting = 2;
		    var doc = Application.ActiveDocument;
    if (!doc) return;

    // 获取或创建上下文菜单栏
    var contextMenus = Application.CommandBars("Text");
    if (!contextMenus) return;

    // 检查是否已经存在名为 "AI" 的菜单项
    var aiMenu = null;
    for (var i = 1; i <= contextMenus.Controls.Count; i++) {
        if (contextMenus.Controls.Item(i).Caption === "AI（本功能由YsDirector编写）") {
            aiMenu = contextMenus.Controls.Item(i);
            break;
        }
    }

    // 如果不存在则创建新的菜单项
    if (!aiMenu) {
        aiMenu = contextMenus.Controls.Add(msoControlPopup);
        aiMenu.Caption = "AI（本功能由YsDirector编写）";
    } else {
        // 清空现有子菜单项
        while (aiMenu.Controls.Count > 0) {
            aiMenu.Controls.Item(1).Delete();
        }
    }

    // 添加子菜单项
    function addMenuItem(menu, caption, macroName) {
        var menuItem = menu.Controls.Add(msoControlButton);
        menuItem.Caption = caption;
        menuItem.OnAction = macroName;
    }

    addMenuItem(aiMenu, "扩写", "LocalAIProcess");
    addMenuItem(aiMenu, "翻译专业英", "LocalAITranslate");
    addMenuItem(aiMenu, "语法检查和更正", "LocalAIGrammarly");
    addMenuItem(aiMenu, "摘要", "LocalAISummary");
    addMenuItem(aiMenu, "关键词", "LocalAIKeywords");
    addMenuItem(aiMenu, "自定义", "LocalAICustomize");
    addMenuItem(aiMenu, "聊天机器人（实验性功能）", "LocalAIChatingBot");
    addMenuItem(aiMenu, "————设置————", );
    addMenuItem(aiMenu, "插入模式", "LocalAISettings1");
    addMenuItem(aiMenu, "替换模式（当前）", "LocalAISettings2");
    addMenuItem(aiMenu, "修订模式", "LocalAISettings3");
        // 刷新屏幕
    Application.ScreenRefresh();
}

function LocalAISettings3(){
	LocalAISetting = 3;
			    var doc = Application.ActiveDocument;
    if (!doc) return;

    // 获取或创建上下文菜单栏
    var contextMenus = Application.CommandBars("Text");
    if (!contextMenus) return;

    // 检查是否已经存在名为 "AI" 的菜单项
    var aiMenu = null;
    for (var i = 1; i <= contextMenus.Controls.Count; i++) {
        if (contextMenus.Controls.Item(i).Caption === "AI（本功能由YsDirector编写）") {
            aiMenu = contextMenus.Controls.Item(i);
            break;
        }
    }

    // 如果不存在则创建新的菜单项
    if (!aiMenu) {
        aiMenu = contextMenus.Controls.Add(msoControlPopup);
        aiMenu.Caption = "AI（本功能由YsDirector编写）";
    } else {
        // 清空现有子菜单项
        while (aiMenu.Controls.Count > 0) {
            aiMenu.Controls.Item(1).Delete();
        }
    }

    // 添加子菜单项
    function addMenuItem(menu, caption, macroName) {
        var menuItem = menu.Controls.Add(msoControlButton);
        menuItem.Caption = caption;
        menuItem.OnAction = macroName;
    }

    addMenuItem(aiMenu, "扩写", "LocalAIProcess");
    addMenuItem(aiMenu, "翻译", "LocalAITranslate");
    addMenuItem(aiMenu, "语法检查和更正", "LocalAIGrammarly");
    addMenuItem(aiMenu, "摘要", "LocalAISummary");
    addMenuItem(aiMenu, "关键词", "LocalAIKeywords");
    addMenuItem(aiMenu, "自定义", "LocalAICustomize");
    addMenuItem(aiMenu, "聊天机器人（实验性功能）", "LocalAIChatingBot");
    addMenuItem(aiMenu, "————设置————", );
    addMenuItem(aiMenu, "插入模式", "LocalAISettings1");
    addMenuItem(aiMenu, "替换模式", "LocalAISettings2");
    addMenuItem(aiMenu, "修订模式（当前）", "LocalAISettings3");
        // 刷新屏幕
    Application.ScreenRefresh();
}

//聊天机器人
function LocalAIChatingBot(){
	UserForm1.Show();
}
//扩写
function LocalAIProcess() {
    const selection = Application.Selection;

    const SelectText = "请您保持原文的核心意思不变增加相关细节和背景信息，使得原文更加完善，请扩写以下文本：" + selection.Text;

    try {
        console.log("AI思考中，请稍候...");
        callLocalAI(SelectText);
    } catch (error) {
        console.error("扩写失败：", error);
        alert("扩写失败：" + error.message);
    }
}
//翻译
function LocalAITranslate() {
    const selection = Application.Selection;

    const SelectText = "请翻译以下内容，注意保持专业简洁：" + selection.Text;

    try {
        console.log("AI思考中，请稍候...");
        callLocalAI(SelectText);
    } catch (error) {
        console.error("翻译失败：", error);
        alert("翻译失败：" + error.message);
    }
}
//检查语法和更正
function LocalAIGrammarly() {
    const selection = Application.Selection;

    const SelectText = "请检查以下内容的语法，并进行更正，注意保持专业简洁：" + selection.Text;

    try {
        console.log("AI思考中，请稍候...");
        callLocalAI(SelectText);
    } catch (error) {
        console.error("执行失败：", error);
        alert("执行失败：" + error.message);
    }
}
//摘要
function LocalAISummary() {
    const selection = Application.Selection;

    const SelectText = "请对以下内容进行归纳总结：" + selection.Text;

    try {
        console.log("AI思考中，请稍候...");
        callLocalAI(SelectText);
    } catch (error) {
        console.error("归纳失败：", error);
        alert("归纳失败：" + error.message);
    }
}
//关键词
function LocalAIKeywords() {
    const selection = Application.Selection;

    const SelectText = "请将以下内容总结成几个关键词：" + selection.Text;

    try {
        console.log("AI思考中，请稍候...");
        callLocalAI(SelectText);
    } catch (error) {
        console.error("归纳失败：", error);
        alert("归纳失败：" + error.message);
    }
}
//自定义要求
function LocalAICustomize() {
    const selection = Application.Selection;

    const SelectText = selection.Text;

    try {
        console.log("AI思考中，请稍候...");
        callLocalAI(SelectText);
    } catch (error) {
        console.error("生成失败：", error);
        alert("生成失败：" + error.message);
    }
}

function callLocalAI(intext) {
    const xhr = new XMLHttpRequest();

    const requestData = JSON.stringify({
        "model": LOCALAI_MODEL,
        "messages": [
            {"role": "system", "content": "你是一个 AI 助理。请严格按照以下要求回复：1. 不要使用任何 Markdown 格式，标题严格使用一、（一）、1的形式，不要带##、**；2. 不要带思考过程（去掉<think></think>内容）；3. 只返回最终结果。"},
            {"role": "user", "content": intext}
        ],
        "temperature": 0.7
    });

    xhr.open("POST", LOCALAI_API_URL, true); // 异步请求
    xhr.setRequestHeader("Content-Type", "application/json");
    xhr.setRequestHeader("Authorization", `Bearer ${LOCALAI_API_KEY}`);

    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
                try {
                    const response = JSON.parse(xhr.responseText);
                    const reText = response.choices[0].message.content;

                    const nPara = ActiveDocument.Content.Paragraphs.Add(ActiveDocument.Paragraphs.Last.Range);
					console.log(LocalAISetting);
					if (LocalAISetting == 1){
                    // 在所选内容后面插入内容
                    Selection.MoveRight(wdCharacter, 1, wdMove);
                    Selection.Text = '\n以下内容由AI生成，请注意甄别：\n' + reText + '\n\n';
                    } 
                    else if(LocalAISetting == 2){
                    	//替换所选内容
                    	Selection.Text =reText;
                    	alert("内容替换成功，由AI生成，请注意甄别");
                    }
                    else if(LocalAISetting == 3){
                    	//启用审阅，替换内容，然后关闭审阅
                    	ActiveDocument.TrackRevisions = true;
                    	Selection.Text =reText;
						ActiveDocument.TrackRevisions = false;
                    }

                    console.log(reText);
                } catch (e) {
                    alert("解析响应失败：" + e.message);
                    console.error("解析响应失败:", e);
                }
            } else {
                alert("API调用失败！状态码：" + xhr.status + " 响应内容：" + xhr.responseText);
                console.error("API调用失败！状态码:", xhr.status, "响应内容:", xhr.responseText);
            }
        }
    };

    xhr.send(requestData);
}

/**
 * UserForm1_CommandButton1_Click Macro
 */
function UserForm1_CommandButton1_Click()
{
    // 获取文本框UserForm1_TextEdit2中的内容
    const inputText = UserForm1.TextEdit2.Value;
    
    // 调用LocalAIChat函数处理输入内容
    LocalAIChat(inputText);
}

function LocalAIChat(SelectText) {
    try {
        console.log("AI思考中，请稍候...");
        chatLocalAI(SelectText);
    } catch (error) {
        console.error("生成失败：", error);
        alert("生成失败：" + error.message);
    }
}

function chatLocalAI(intext) {
    const xhr = new XMLHttpRequest();

    const requestData = JSON.stringify({
        "model": LOCALAI_MODEL,
        "messages": [
            {"role": "system", "content": ""},
            {"role": "user", "content": intext}
        ],
        "temperature": 0.7
    });

    xhr.open("POST", LOCALAI_API_URL, true); // 异步请求
    xhr.setRequestHeader("Content-Type", "application/json");
    xhr.setRequestHeader("Authorization", `Bearer ${LOCALAI_API_KEY}`);

    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
                try {
                    const response = JSON.parse(xhr.responseText);
                    const reText = response.choices[0].message.content;

                    // 将生成的内容返回到UserForm1_TextEdit1中
                    UserForm1.TextEdit1.Value = reText;

                    console.log(reText);
                } catch (e) {
                    alert("解析响应失败：" + e.message);
                    console.error("解析响应失败:", e);
                }
            } else {
                alert("API调用失败！状态码：" + xhr.status + " 响应内容：" + xhr.responseText);
                console.error("API调用失败！状态码:", xhr.status, "响应内容:", xhr.responseText);
            }
        }
    };

    xhr.send(requestData);
}